<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<!-- 深拷贝的目的其实就是把简单数据类型直接返回，复杂数据类型就转成简单数据类型，因为简单数据类型就是深拷贝，
    其实感觉对象里的{a:1,b:2}中的1，2就是一个简单数据类型 -->
<body>
    <script>
        // target是我的目标对象，是一个空对象，source是我的原对象，
        // 首先我遍历age,然后 let sourceValue = source[key];中的值就为12
        // 然后12不是一个对象，然后我就进入else了，然后target.age = 12,

        // 然后就是key对于say,然后let sourceValue = source[key];中的值为{speak: "归还借款",}
        // 然后是一个对象，所以进入if,然后subTarget等于一个空对象，target[key] = subTarget;
        // 也就是target.say = {},然后再进行递归，然后我就把空对象和{speak: "归还借款",}再次调用
        // 然后我的 let sourceValue = source[key];等于归还借款，进入else,里面一层的say{}中，
        // target.speak = "归还借款";
        function deCopy(target, source) {
            // 1.通过遍历拿到source中所有的属性
            for (let key in source) {
                // 2.取出当前遍历到的属性对应的取值
                let sourceValue = source[key];
                console.log("source[key]",source[key])
                console.log("sourceValue",sourceValue)
                // 3.判断当前的取值是否是引用数据类型
                if (sourceValue instanceof Object) { // 如果是引用数据类型, 那么要新建一个存储空间保存
                    // 4.通过sourceValue.constructor拿到这个对象的构造函数的类型, 然后新建这个对象或数组
                    let subTarget = new sourceValue.constructor;//new Object()和new sourceValue.constructor一样的，就是新建一个对象
                    console.log(subTarget)
                    target[key] = subTarget;
                    
                    // 5.再次调用拷贝, 将遍历到的属性的取值拷贝给新建的对象或者数组
                    deCopy(subTarget, sourceValue);
                    console.log("target[key]",target[key])
                    console.log("subTarget",subTarget)
                } else { // 如果不是引用数据类型, 之间将属性拷贝即可
                    target[key] = sourceValue;
                }
            }
        }

        var a = {
            // name: "jjk",
            age: "12",
            say: {
                speak: "归还借款",
            }
        }


        var a1 = {}
        deCopy(a1, a);
        a1.say.speak = 666; // 修改新变量的值不会影响到原有变量, 这里是深拷贝
        console.log(a.say.speak); // "归还借款",
        console.log(a1.say.speak); // 666
        console.log(a);
        console.log(a1)



        //  function deCopy(obj) {
        //     // 如果不是引用数据类型, 直接将属性拷贝即可
        //     if (typeof obj != 'object') return obj
        //     // 如果是引用数据类型, 那么要新建一个存储空间保存
        //     // constructor这里的constructor可以不用打括号，new关键字可以帮我们执行
        //     let newObj = new obj.constructor   //new Object()和obj.constructor一样的，就是新建一个对象
        //     for (let key in obj) {
        //         // 递归调用拷贝, 将遍历到的属性的取值拷贝给新建的对象或者数组
        //         console.log("key",key);
        //         // 这里用[]是因为我的key是未知的，要是已知，就用.key
        //         这里的key其实拿的就是我for (let key in obj)里面遍历的，因为我这里的可以拿的是对象a中的
        //         newObj[key] = deCopy(obj[key])   //  //
        //         console.log("newObj[key]",newObj[key])
        //         // console.log("deCopy(obj[key])",deCopy(obj[key]))

        //     }
        //     return newObj
        // }

        


        // var a = {
        //     say: {
        //         speak: "归还借款",
        //     }
        // }
        // // let b = deCopy(a);
        // // a.say.speak = "法国红酒"
        // deCopy(a)
        // console.log(b);
        // console.log(new Object)

        // function Fn(name){
        //     this.name = name;
        // }
        // console.log(new Fn);
    </script>
</body>

</html>